#ifndef __UTIL_HPP__
   #define __UTIL_HPP__

#include "log.hpp"
#include <fstream>
#include <mysql/mysql.h>
#include <jsoncpp/json/json.h>
#include <sstream>
#include <fstream>
#include <memory>
#include <vector>
#include <string>

class read_file_util
{
public:
    static bool read_file(const std::string &name, std::string &str)//读取文件内容
    {
        std::ifstream file;

        // 以二进制方式打开
        file.open(name.c_str(), std::ios::binary);

        if (!file.is_open()) // 打开失败,一般性错误
        {
            error_log("%s file open error", name.c_str());
            return false;
        }

        // 开始读取，先拿到文件大小
        file.seekg(0, std::ios::end);
        int size = file.tellg();
        str.resize(size);

        file.seekg(std::ios::beg);

        // 读取放入str
        file.read((char *)str.c_str(), size);

        if (!file.good()) //读取失败,一般性错误
        {
            error_log("%s file read error", name.c_str());
            file.close();
            return false;
        }

        // 关闭
        file.close();
        return true;
    }
};

class mysql_util // cmysql的功能封装1
{
public:
    static MYSQL *mysql_create(const std::string &host,
                               const std::string &user,
                               const std::string &password,
                               const std::string &dp,
                               const uint16_t port)
    {
        // 创建mysql句柄
        MYSQL *mysql = mysql_init(nullptr);
        if (mysql == nullptr)
        {
            fatal_log("mysql_init error");
            return nullptr;
        }

        // 进行连接
        if (!mysql_real_connect(mysql, host.c_str(), user.c_str(), password.c_str(), dp.c_str(), port, nullptr, 0))
        {
            error_log("mysql_real_connect error");
            return nullptr;
        }

        return mysql;
    }

    static bool mysql_query_one(MYSQL *mysql, const std::string &query)
    {
        int ret = mysql_query(mysql, query.c_str());
        if (ret != 0)
        {
            error_log("mysql_query error: %s", query.c_str());
            return false;
        }
        return true;
    }

    static void mysql_destory(MYSQL *mysql)
    {
        if (mysql != nullptr)
            mysql_close(mysql);
    }
};

class json_util //json的序列化与反序列化
{
public:
    static bool serialize(const Json::Value &root, std::string &str)
    {
        Json::StreamWriterBuilder builder;
        std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
        std::ostringstream oss;
        writer->write(root, &oss);

        str = oss.str();
        return true;
    }

    static bool unserialize(Json::Value &root, const std::string &str)
    {
        Json::CharReaderBuilder builder;
        std::unique_ptr<Json::CharReader> reader(builder.newCharReader());

        std::string buffer;
        std::string error;
        reader->parse(str.c_str(), str.c_str() + str.size(), &root, nullptr);
        return true;
    }
};

class string_util //string功能函数实现
{
public:
    // 按分隔符切割，并且将切割结果放入到 vector中
    static void str_cut(const std::string &str, const std::string &esp, std::vector<std::string> &v)
    {
        if (str.empty() || esp.empty())
            return;
        int bpos = 0;
        int epos = 0;
        int sesp = esp.size();
        while (1)
        {
            epos = str.find(esp, bpos);
            if (epos == std::string::npos)
            {
                // 没找到，将没加入vector的全部加入
                v.push_back(str.substr(bpos));
                break;
            }
            else
            {
                // 找到了,将bpos 到 epos中的加入到 v
                v.push_back(str.substr(bpos, epos - bpos));
                do
                {
                    epos += sesp;
                    if (epos == str.size())
                    {
                        // 找到结尾,直接返回
                        return;
                    }
                    if (str.substr(epos, sesp) != esp)
                    {
                        bpos = epos;
                        break;
                    }

                } while (1);
            }
        }
    }
};

#endif